import { findDOM, compareTwoVdom } from './react-dom';
// 批量更新
export let updateQueue = {
    isBatchingUpdate: false, // 是否批量更新
    updaters: [],
    batchUpdate() {
        for (let updater of updateQueue.updaters) {
            updater.updateComponent();
        }
        updateQueue.isBatchingUpdate = false;
        updateQueue.updaters.length = 0;
    }
}
// 每个类组件实例有一个updater更新器
class Updater {
    constructor(classInstance) {
        this.classInstance = classInstance;
        this.pendingStates = []; // 保存将要更新的队列，可能是对象，也可能是函数
        this.callbacks = []; // 保存将要执行的回调函数
    }
    // 根据老状态和pendingStates更新队列，执行回调，获取新状态
    getState() {
        let { classInstance, pendingStates } = this;
        let { state } = classInstance; // 先拿到老状态
        // 执行更新队列，覆盖老状态
        pendingStates.forEach(nextState => {
            if (typeof nextState === 'function') {
                nextState = nextState(state);
            }
            state = { ...state, ...nextState };
        })
        // 清空等待更新队列
        pendingStates.length = 0;
        // 执行所有回调
        this.callbacks.forEach(cb => cb());
        this.callbacks.length = 0;
        // 返回新状态
        return state;
    }
    addState(partialState, callback) {
        // 第一个参数，可能是对象，也可能是函数
        this.pendingStates.push(partialState);
        // 第二个参数，回调函数
        if (typeof callback === 'function') {
            this.callbacks.push(callback);
        }
        // 触发更新
        this.emitUpdate();
    }
    // 状态和属性变化都执行此方法，让组件更新
    emitUpdate(nextProps) {
        this.nextProps = nextProps;
        // 批量更新模式
        if (updateQueue.isBatchingUpdate) {
            updateQueue.updaters.push(this);
        // 非批量更新模式
        } else {
            this.updateComponent();
        }
    }
    updateComponent() {
        let { classInstance, pendingStates, nextProps } = this;
        // 有等待更新，执行队列函数，获取最新状态
        if (nextProps || pendingStates.length > 0) {
            shouldUpdate(classInstance, nextProps, this.getState());
        }
    }
}

// 更新视图
function shouldUpdate(classInstance, nextProps, nextState) {
    // 生命周期
    let willUpdate = true; // 是否更新
    if (classInstance.shouldComponentUpdate && !classInstance.shouldComponentUpdate(nextProps, nextState)) {
        willUpdate = false;
    }
    if (willUpdate && classInstance.componentWillUpdate) {
        classInstance.componentWillUpdate();
    }
    // 更新属性
    if (nextProps) classInstance.props = nextProps;
    // 修改实例状态
    classInstance.state = nextState;
    // 调用类组件的方法更新
    if (willUpdate) {
        classInstance.forceUpdate();
    }
}

// 类组件
export class Component {
    static isReactComponent = true; // 类组件标识
    constructor(props) {
        this.props = props;
        this.state = {};
        // 每个类组件实例都有一个updater更新器
        this.updater = new Updater(this);
    }
    setState(partialState, callback) {
        this.updater.addState(partialState, callback);
    }
    // 组件更新，diff
    forceUpdate() {
        // 获取新老虚拟dom
        let oldRenderVdom = this.oldRenderVdom;
        let newRenderVdom = this.render();
        // 获取挂载点
        let oldDOM = findDOM(oldRenderVdom);
        // 比较差异，更新视图
        compareTwoVdom(oldDOM.parentNode, oldRenderVdom, newRenderVdom);
        // 更新实例上的虚拟dom
        this.oldRenderVdom = newRenderVdom;
        // 生命周期
        if(this.componentDidUpdate) {
            this.componentDidUpdate(this.props, this.state);
        }
    }
}